package com.yanqu.road.server.manager.activity.unionchest;

import com.yanqu.road.dao.impl.activity.unionchest.CrossUnionChestBoxDaoImpl;
import com.yanqu.road.dao.impl.activity.unionchest.CrossUnionChestNoticeDaoImpl;
import com.yanqu.road.dao.impl.activity.unionchest.CrossUnionChestUserDaoImpl;
import com.yanqu.road.entity.activity.unionChest.CrossUnionChestBoxData;
import com.yanqu.road.entity.activity.unionChest.CrossUnionChestNoticeData;
import com.yanqu.road.entity.activity.unionChest.CrossUnionChestUserData;
import com.yanqu.road.entity.activity.unionChest.UnionChestBoxInfo;
import com.yanqu.road.entity.activity.unionChest.config.UnionChestBoxConfig;
import com.yanqu.road.entity.activity.unionChest.config.UnionChestConfig;
import com.yanqu.road.entity.config.goods.OpenGoodsBagResult;
import com.yanqu.road.entity.player.CrossUserBaseInfo;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.pb.CrossActivityPb;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.activity.UnionChestProto;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.manger.TempGoodsBagMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class UnionChestActivity {
    private int activityId;
    private Map<String, CrossUnionChestInfo> unionChestInfoMap = new ConcurrentHashMap<>();
    private Map<Long, CrossUnionChestUserData> userDataMap = new ConcurrentHashMap<>();

    private LinkedList<CrossUnionChestNoticeData> noticeDataList = new LinkedList<>();
    private List<CrossUnionChestNoticeData> needInsertNotice = new ArrayList<>();


    public UnionChestActivity(int activityId) {
        this.activityId = activityId;
        loadDb();
    }

    private void loadDb() {
        UnionChestConfig config = CrossUnionChestConfigMgr.getConfigMap().get(activityId);
        if (null == config) {
            return;
        }
        userDataMap = new CrossUnionChestUserDaoImpl().getCrossUnionChestUserDataMap(activityId);
        List<CrossUnionChestNoticeData> tempNoticeDataList = new CrossUnionChestNoticeDaoImpl().getCrossUnionChestNoticeDataMap(activityId);
        Map<String, Map<Long, CrossUnionChestBoxData>> tempBoxDataMap = new CrossUnionChestBoxDaoImpl().getCrossUnionChestBoxDataMap(activityId);
        for (Map.Entry<String, Map<Long, CrossUnionChestBoxData>> entry : tempBoxDataMap.entrySet()) {
            String unionId = entry.getKey();
            CrossUnionChestInfo unionChsetInfo = getUnionChsetInfo(unionId);
            unionChsetInfo.initByDb(entry.getValue());
        }

        tempNoticeDataList.sort((o1, o2) -> Long.compare(o2.getOpendTime(), o1.getOpendTime()));
        for (int i = 0; i < tempNoticeDataList.size() && i < config.getNoticeNum(); i++) {
            noticeDataList.addFirst(tempNoticeDataList.get(i));
        }
    }

    public void save() {
        for (Long userId : userDataMap.keySet()) {
            CrossUnionChestUserData userData = userDataMap.get(userId);
            if (userData.isInsertOption()) {
                new CrossUnionChestUserDaoImpl().add(userData);
            } else if (userData.isUpdateOption()) {
                new CrossUnionChestUserDaoImpl().update(userData);
            }
        }

        for (CrossUnionChestInfo unionChestInfo : unionChestInfoMap.values()) {
            for (CrossUnionChestBoxData boxData : unionChestInfo.getBoxDataList()) {
                if (boxData.isInsertOption()) {
                    new CrossUnionChestBoxDaoImpl().add(boxData);
                } else if (boxData.isUpdateOption()) {
                    new CrossUnionChestBoxDaoImpl().update(boxData);
                }
            }

            new CrossUnionChestNoticeDaoImpl().addNoticeListData(popNeedInsertNotice());
        }

    }

    public CrossUnionChestInfo getUnionChsetInfo(String unionId) {
        if (StringUtils.isNullOrEmpty(unionId)) {
            return null;
        }
        CrossUnionChestInfo unionChestInfo = unionChestInfoMap.get(unionId);
        if (null == unionChestInfo) {
            unionChestInfo = new CrossUnionChestInfo(activityId, unionId);
            unionChestInfoMap.put(unionId, unionChestInfo);
        }
        return unionChestInfo;
    }

    public CrossUnionChestUserData getUserData(long userId) {
        CrossUnionChestUserData userData = userDataMap.get(userId);
        if (null == userData) {
            synchronized (userDataMap) {
                userData = userDataMap.get(userId);
                if (null == userData) {
                    userData = new CrossUnionChestUserData(activityId, userId);
                    userDataMap.put(userId, userData);
                }
            }
        }
        return userData;
    }

    public int getUserOpenNum(long userId) {
        CrossUnionChestUserData userData = getUserData(userId);
        if (!DateHelper.isToday(new Date(userData.getLastOpenTime()))) {
            userData.setOpenNum(0);
            userData.setLastOpenTime(DateHelper.getCurrentTime());
        }
        return userData.getOpenNum();
    }

    public UnionChestProto.UnionChestUserSyncMsg.Builder getUserSyncMsg(long userId, String unionId) {
        UnionChestProto.UnionChestUserSyncMsg.Builder builder = UnionChestProto.UnionChestUserSyncMsg.newBuilder();
        builder.setActivityId(activityId);
        builder.setDailyNum(getUserOpenNum(userId));
        builder.addAllBoxList(getBoxMsgList(unionId));
        return builder;
    }

    /**
     * 商会宝箱列表
     */
    public List<UnionChestProto.UnionChestBoxTemp> getBoxMsgList(String unionId) {
        List<UnionChestProto.UnionChestBoxTemp> boxTempList = new ArrayList<>();
        CrossUnionChestInfo unionChsetInfo = getUnionChsetInfo(unionId);
        if (null == unionChsetInfo) {
            return boxTempList;
        }
        for (CrossUnionChestBoxData chestBoxData : unionChsetInfo.getBoxDataList()) {
            boxTempList.add(parseUnionBoxMsg(chestBoxData).build());
        }

        return boxTempList;
    }

    public UnionChestProto.UnionChestBoxTemp.Builder parseUnionBoxMsg(CrossUnionChestBoxData chestBoxData) {
        UnionChestProto.UnionChestBoxTemp.Builder builder = UnionChestProto.UnionChestBoxTemp.newBuilder();
        builder.setBoxId(chestBoxData.getBoxId());
        builder.setBoxType(chestBoxData.getBoxType());
        UserBaseInfo userBaseInfo = CrossUserMgr.getUserBaseInfo(chestBoxData.getShareUserId());
        if (null != userBaseInfo) {
            builder.setUserBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userBaseInfo));
        }
        builder.setShareTime(chestBoxData.getShareTime());
        builder.setShareUserId(chestBoxData.getShareUserId());
        UnionChestConfig config = CrossUnionChestConfigMgr.getConfigMap().get(activityId);
        UnionChestBoxConfig boxConfig = config.getBoxMap().get(chestBoxData.getBoxType());
        for (int i = 0; i < boxConfig.getNum(); i++) {
            UnionChestBoxInfo boxInfo = chestBoxData.getBoxInfoMap().get(i);
            if (null == boxInfo) {
                boxInfo = new UnionChestBoxInfo(i);
            }
            builder.addBoxRewardList(CrossActivityPb.parseUnionChestBoxRewardMsg(boxInfo));
        }
        return builder;
    }

    /**
     * 分享宝箱
     */
    public UnionChestProto.CrossUnionChestShareBoxRespMsg.Builder shareBox(long userId, String unionId, int boxType) {
        UnionChestProto.CrossUnionChestShareBoxRespMsg.Builder builder = UnionChestProto.CrossUnionChestShareBoxRespMsg.newBuilder();
        builder.setRet(0);
        builder.setActivityId(activityId);
        UnionChestConfig config = CrossUnionChestConfigMgr.getConfigMap().get(activityId);
        if (null == config) {
            return builder.setRet(GameErrorCode.E_ACTIVITY_NO_FOUND);
        }
        UnionChestBoxConfig boxConfig = config.getBoxMap().get(boxType);
        if (null == boxConfig) {
            return builder.setRet(GameErrorCode.E_ERROR_DATA);
        }

        CrossUnionChestInfo unionChsetInfo = getUnionChsetInfo(unionId);
        CrossUnionChestBoxData chestBoxData = unionChsetInfo.shareBox(userId, boxConfig);
        builder.setBox(parseUnionBoxMsg(chestBoxData));
        builder.setUnionId(unionId);
        builder.setBoxGoodsId(boxConfig.getBoxId());
        builder.setUserId(userId);

        return builder;
    }

    /**
     * 开宝箱
     */
    public UnionChestProto.UnionChestBoxOpenBoxRespMsg.Builder openBox(long userId, String userName, String unionId, long boxId, int boxIndex) {
        UnionChestProto.UnionChestBoxOpenBoxRespMsg.Builder builder = UnionChestProto.UnionChestBoxOpenBoxRespMsg.newBuilder();
        builder.setActivityId(activityId);
        builder.setRet(0);
        CrossUnionChestInfo unionChsetInfo = getUnionChsetInfo(unionId);
        if (null == unionChsetInfo) {
            return builder.setRet(GameErrorCode.E_ERROR_DATA);
        }

        getUserOpenNum(userId);
        CrossUnionChestUserData userData = getUserData(userId);
        if (null == userData) {
            return builder.setRet(GameErrorCode.E_ERROR_DATA);
        }


        synchronized (unionChsetInfo) {

            CrossUnionChestBoxData boxData = unionChsetInfo.getBoxData(boxId);
            if (null == boxData) {
                return builder.setRet(GameErrorCode.E_UNIONCHEST_BOX_NOT_FOUND);
            }
            UnionChestConfig config = CrossUnionChestConfigMgr.getConfigMap().get(activityId);
            if (null == config) {
                return builder.setRet(GameErrorCode.E_ACTIVITY_NO_FOUND);
            }
            if (userData.getOpenNum() >= config.getDailyDrawNum()) {
                return builder.setRet(GameErrorCode.E_UNIONCHEST_DAILY_OPEN_MAX);
            }
            UnionChestBoxConfig boxConfig = config.getBoxMap().get(boxData.getBoxType());
            if (null == boxConfig) {
                return builder.setRet(GameErrorCode.E_ERROR_DATA);
            }
            if (boxIndex >= boxConfig.getNum() || boxIndex < 0) {
                return builder.setRet(GameErrorCode.E_UNIONCHEST_BOX_NOT_ENOUGH);
            }

            //一个分享宝箱，一个玩家只能开一次
            int openNum = 0;
            for (UnionChestBoxInfo boxInfo : boxData.getBoxInfoMap().values()) {
                if (boxInfo.getOpenUserId() == userId) {
                    return builder.setRet(GameErrorCode.E_UNIONCHEST_BOX_SHARE_OPEN);
                }
                openNum++;
            }
            if (openNum >= boxConfig.getNum()) {
                return builder.setRet(GameErrorCode.E_UNIONCHEST_BOX_NOT_ENOUGH);
            }

            //第一个宝箱是专属宝箱
            if (boxIndex == 0) {
                if (userId != boxData.getShareUserId()) {
                    return builder.setRet(GameErrorCode.E_UNIONCHEST_BOX_ONLY_SHARE);
                }
            }

            UnionChestBoxInfo boxInfo = boxData.getBoxInfoMap().get(boxIndex);
            if (null != boxInfo) {
                return builder.setRet(GameErrorCode.E_UNIONCHEST_BOX_ALREADY_OPEN);
            }

            if (boxIndex != 0) {//领专属宝箱不占用次数
                userData.setOpenNum(userData.getOpenNum() + 1);
            }

            userData.setLastOpenTime(DateHelper.getCurrentTime());

            // 领取奖励
            OpenGoodsBagResult openResult = TempGoodsBagMgr.getRandomGoods(boxConfig.getBoxId());
            builder.setReward(PropertyHelper.parsePropertyToString(openResult.getReward()));

            boxInfo = new UnionChestBoxInfo(boxIndex);
            boxInfo.setOpenName(userName);
            boxInfo.setOpenUserId(userId);
            boxInfo.setOpenTime(DateHelper.getCurrentTime());
            boxInfo.setRewards(builder.getReward());
            boxData.addBoxInfo(boxInfo);

            builder.setBox(parseUnionBoxMsg(boxData));
        }
        builder.setDailyNum(getUserOpenNum(userId));

        return builder;
    }

    public UnionChestProto.UnionChestNoticeListRespMsg.Builder getNoticeListMsg(String unionId) {
        UnionChestProto.UnionChestNoticeListRespMsg.Builder builder = UnionChestProto.UnionChestNoticeListRespMsg.newBuilder();
        builder.setRet(0);
        builder.setActivityId(activityId);
        for (CrossUnionChestNoticeData noticeData : getNoticeList()) {
            builder.addBoxNotice(CrossActivityPb.parseUnionChestNoticeMsg(noticeData));
        }

        return builder;
    }

    public List<CrossUnionChestNoticeData> popNeedInsertNotice() {
        synchronized (needInsertNotice) {
            List<CrossUnionChestNoticeData> list = new ArrayList<>(needInsertNotice);
            needInsertNotice.clear();
            return list;
        }
    }

    public void addNotice(CrossUnionChestNoticeData noticeData, int maxNum) {
        synchronized (needInsertNotice) {
            needInsertNotice.add(noticeData);
        }

        synchronized (noticeDataList) {
            noticeDataList.addFirst(noticeData);
            while (noticeDataList.size() > maxNum) {
                noticeDataList.removeLast();
            }
        }
    }

    public List<CrossUnionChestNoticeData> getNoticeList() {
        synchronized (noticeDataList) {
            List<CrossUnionChestNoticeData> list = new ArrayList<>(noticeDataList);
            return list;
        }
    }

    public void addNoticeMsg(UnionChestProto.CrossUnionChestNoticeAddMsg msg) {
        CrossUnionChestInfo unionChsetInfo = getUnionChsetInfo(msg.getUnionId());
        if (null == unionChsetInfo) {
            return;
        }
        CrossUnionChestBoxData boxData = unionChsetInfo.getBoxData(msg.getBoxId());
        if (null == boxData) {
            return;
        }
        UnionChestBoxInfo boxInfo = boxData.getBoxInfoMap().get(msg.getBoxIndex());
        if (null == boxInfo) {
            return;
        }

        UnionChestConfig config = CrossUnionChestConfigMgr.getConfigMap().get(activityId);
        if (null == config){
            return;
        }

        String shareName = "";
        CrossUserBaseInfo crossUserBaseInfo = CrossUserMgr.getCrossUserBaseInfo(boxData.getShareUserId());
        if (null != crossUserBaseInfo) {
            shareName = crossUserBaseInfo.getUserBaseInfo().getNickName();
        }

        CrossUnionChestNoticeData noticeData = new CrossUnionChestNoticeData(activityId, msg.getUnionId(), msg.getBoxId(), boxData.getBoxType(),
                shareName, boxInfo.getOpenUserId(), boxInfo.getOpenName(), boxInfo.getOpenTime(), boxInfo.getRewards());
        addNotice(noticeData, config.getNoticeNum());

    }
}
